From 904835d4b1ad1f04743e7bd51a3479a4e71b82c7 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 22 Mar 2020 09:16:57 -0400 Subject: [PATCH] shortcuttrigger: Introduce partial matches Allow GtkShortcutTrigger to return partial matches. Currently, no triggers produce such results, and GtkShortcutController treats partial matches like exact ones. --- gtk/gtkshortcutcontroller.c | 2 +- gtk/gtkshortcuttrigger.c | 47 +++++++++++++++++++------------------ gtk/gtkshortcuttrigger.h | 21 ++++++++++++++++- testsuite/gtk/shortcuts.c | 14 +++++------ 4 files changed, 52 insertions(+), 32 deletions(-) diff --git a/gtk/gtkshortcutcontroller.c b/gtk/gtkshortcutcontroller.c index f85662b332..31c12d0195 100644 --- a/gtk/gtkshortcutcontroller.c +++ b/gtk/gtkshortcutcontroller.c @@ -247,7 +247,7 @@ gtk_shortcut_controller_trigger_shortcut (GtkShortcutController *self, { GtkWidget *widget; - if (!gtk_shortcut_trigger_trigger (gtk_shortcut_get_trigger (shortcut), event, enable_mnemonics)) + if (gtk_shortcut_trigger_trigger (gtk_shortcut_get_trigger (shortcut), event, enable_mnemonics) == GTK_SHORTCUT_TRIGGER_MATCH_NONE) return FALSE; widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)); diff --git a/gtk/gtkshortcuttrigger.c b/gtk/gtkshortcuttrigger.c index 064dae4d3f..828a8486d2 100644 --- a/gtk/gtkshortcuttrigger.c +++ b/gtk/gtkshortcuttrigger.c @@ -59,7 +59,8 @@ struct _GtkShortcutTriggerClass const char *type_name; void (* finalize) (GtkShortcutTrigger *trigger); - gboolean (* trigger) (GtkShortcutTrigger *trigger, + GtkShortcutTriggerMatch + (* trigger) (GtkShortcutTrigger *trigger, GdkEvent *event, gboolean enable_mnemonics); guint (* hash) (GtkShortcutTrigger *trigger); @@ -166,17 +167,16 @@ gtk_shortcut_trigger_get_trigger_type (GtkShortcutTrigger *self) * value of this property is determined by checking that the passed * in @event is a Key event and has the right modifiers set. * - * Checks if the given @event triggers @self. If so, - * returns %TRUE. + * Checks if the given @event triggers @self. * - * Returns: %TRUE if this event triggered the trigger + * Returns: Whether the event triggered the shortcut **/ -gboolean +GtkShortcutTriggerMatch gtk_shortcut_trigger_trigger (GtkShortcutTrigger *self, GdkEvent *event, gboolean enable_mnemonics) { - g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (self), FALSE); + g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (self), GTK_SHORTCUT_TRIGGER_MATCH_NONE); return self->trigger_class->trigger (self, event, enable_mnemonics); } @@ -411,12 +411,12 @@ gtk_never_trigger_finalize (GtkShortcutTrigger *trigger) g_assert_not_reached (); } -static gboolean +static GtkShortcutTriggerMatch gtk_never_trigger_trigger (GtkShortcutTrigger *trigger, GdkEvent *event, gboolean enable_mnemonics) { - return FALSE; + return GTK_SHORTCUT_TRIGGER_MATCH_NONE; } static guint @@ -493,7 +493,7 @@ gtk_keyval_trigger_finalize (GtkShortcutTrigger *trigger) { } -static gboolean +static GtkShortcutTriggerMatch gtk_keyval_trigger_trigger (GtkShortcutTrigger *trigger, GdkEvent *event, gboolean enable_mnemonics) @@ -503,7 +503,7 @@ gtk_keyval_trigger_trigger (GtkShortcutTrigger *trigger, guint keyval; if (gdk_event_get_event_type (event) != GDK_KEY_PRESS) - return FALSE; + return GTK_SHORTCUT_TRIGGER_MATCH_NONE; /* XXX: This needs to deal with groups */ modifiers = gdk_event_get_modifier_state (event); @@ -514,7 +514,10 @@ gtk_keyval_trigger_trigger (GtkShortcutTrigger *trigger, else keyval = gdk_keyval_to_lower (keyval); - return keyval == self->keyval && modifiers == self->modifiers; + if (keyval != self->keyval || modifiers != self->modifiers) + return GTK_SHORTCUT_TRIGGER_MATCH_NONE; + + return GTK_SHORTCUT_TRIGGER_MATCH_EXACT; } static guint @@ -659,7 +662,7 @@ gtk_mnemonic_trigger_finalize (GtkShortcutTrigger *trigger) { } -static gboolean +static GtkShortcutTriggerMatch gtk_mnemonic_trigger_trigger (GtkShortcutTrigger *trigger, GdkEvent *event, gboolean enable_mnemonics) @@ -668,10 +671,10 @@ gtk_mnemonic_trigger_trigger (GtkShortcutTrigger *trigger, guint keyval; if (!enable_mnemonics) - return FALSE; + return GTK_SHORTCUT_TRIGGER_MATCH_NONE; if (gdk_event_get_event_type (event) != GDK_KEY_PRESS) - return FALSE; + return GTK_SHORTCUT_TRIGGER_MATCH_NONE; /* XXX: This needs to deal with groups */ keyval = gdk_key_event_get_keyval (event); @@ -681,7 +684,10 @@ gtk_mnemonic_trigger_trigger (GtkShortcutTrigger *trigger, else keyval = gdk_keyval_to_lower (keyval); - return keyval == self->keyval; + if (keyval != self->keyval) + return GTK_SHORTCUT_TRIGGER_MATCH_NONE; + + return GTK_SHORTCUT_TRIGGER_MATCH_EXACT; } static guint @@ -814,20 +820,15 @@ gtk_alternative_trigger_finalize (GtkShortcutTrigger *trigger) gtk_shortcut_trigger_unref (self->second); } -static gboolean +static GtkShortcutTriggerMatch gtk_alternative_trigger_trigger (GtkShortcutTrigger *trigger, GdkEvent *event, gboolean enable_mnemonics) { GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger; - if (gtk_shortcut_trigger_trigger (self->first, event, enable_mnemonics)) - return TRUE; - - if (gtk_shortcut_trigger_trigger (self->second, event, enable_mnemonics)) - return TRUE; - - return FALSE; + return MAX (gtk_shortcut_trigger_trigger (self->first, event, enable_mnemonics), + gtk_shortcut_trigger_trigger (self->second, event, enable_mnemonics)); } static guint diff --git a/gtk/gtkshortcuttrigger.h b/gtk/gtkshortcuttrigger.h index b0ab8af862..627072ea53 100644 --- a/gtk/gtkshortcuttrigger.h +++ b/gtk/gtkshortcuttrigger.h @@ -51,6 +51,25 @@ typedef enum { GTK_SHORTCUT_TRIGGER_ALTERNATIVE } GtkShortcutTriggerType; +/** + * GtkShortcutTriggerMatch: + * @GTK_SHORTCUT_TRIGGER_MATCH_NONE: The key event does not + * match the trigger + * @GTK_SHORTCUT_TRIGGER_MATCH_PARTIAL: The key event matches + * the trigger if keyboard state (specifically, the currently + * active group) is ignored + * @GTK_SHORTCUT_TRIGGER_MATCH_EXACT: The key event matches + * the trigger + * + * The possible return values from gtk_shortcut_trigger_trigger() + * describe if a key event triggers a shortcut. + */ +typedef enum { + GTK_SHORTCUT_TRIGGER_MATCH_NONE, + GTK_SHORTCUT_TRIGGER_MATCH_PARTIAL, + GTK_SHORTCUT_TRIGGER_MATCH_EXACT, +} GtkShortcutTriggerMatch; + GDK_AVAILABLE_IN_ALL GType gtk_shortcut_trigger_get_type (void) G_GNUC_CONST; @@ -88,7 +107,7 @@ gint gtk_shortcut_trigger_compare (gconstpointer gconstpointer trigger2); GDK_AVAILABLE_IN_ALL -gboolean gtk_shortcut_trigger_trigger (GtkShortcutTrigger *self, +GtkShortcutTriggerMatch gtk_shortcut_trigger_trigger (GtkShortcutTrigger *self, GdkEvent *event, gboolean enable_mnemonics); diff --git a/testsuite/gtk/shortcuts.c b/testsuite/gtk/shortcuts.c index 757b2803e4..e06b1814e9 100644 --- a/testsuite/gtk/shortcuts.c +++ b/testsuite/gtk/shortcuts.c @@ -195,14 +195,14 @@ test_trigger_trigger (void) guint keyval; GdkModifierType state; gboolean mnemonic; - gboolean result[4]; + GtkShortcutTriggerMatch result[4]; } tests[] = { - { GDK_KEY_a, GDK_CONTROL_MASK, FALSE, { 0, 1, 0, 1 } }, - { GDK_KEY_a, GDK_CONTROL_MASK, TRUE, { 0, 1, 0, 1 } }, - { GDK_KEY_a, GDK_SHIFT_MASK, FALSE, { 0, 0, 0, 0 } }, - { GDK_KEY_a, GDK_SHIFT_MASK, TRUE, { 0, 0, 0, 0 } }, - { GDK_KEY_u, GDK_SHIFT_MASK, FALSE, { 0, 0, 0, 0 } }, - { GDK_KEY_u, GDK_SHIFT_MASK, TRUE, { 0, 0, 1, 1 } }, + { GDK_KEY_a, GDK_CONTROL_MASK, FALSE, { GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_EXACT, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_EXACT } }, + { GDK_KEY_a, GDK_CONTROL_MASK, TRUE, { GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_EXACT, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_EXACT } }, + { GDK_KEY_a, GDK_SHIFT_MASK, FALSE, { GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE } }, + { GDK_KEY_a, GDK_SHIFT_MASK, TRUE, { GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE } }, + { GDK_KEY_u, GDK_SHIFT_MASK, FALSE, { GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE } }, + { GDK_KEY_u, GDK_SHIFT_MASK, TRUE, { GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_NONE, GTK_SHORTCUT_TRIGGER_MATCH_EXACT, GTK_SHORTCUT_TRIGGER_MATCH_EXACT } }, }; int i; -- 2.30.2